package br.com.ava.core.autenticacao;

import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSession;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import br.com.ava.core.ConstantesMensagens;
import br.com.ava.core.infra.excecao.NegocioException;
import br.com.ava.core.usuario.Usuario;

/**
 * Mediator utilizado para autenticação de usuários.
 */
public class AutenticacaoService implements UserDetailsService {

	// private FuncionaMediator funcionaMediator;
	private AuthenticationManager authenticationManager;

	/**
	 * Realiza o login no sistema.
	 * 
	 * @param login
	 *            Login do usuário.
	 * @param senha
	 *            Senha do usuário.
	 */
	public void autenticar(String login, String senha) throws NegocioException {
		try {
			UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
					login, senha);

			Authentication authenticate = authenticationManager
					.authenticate(token);
			if (authenticate.isAuthenticated()) {
				SecurityContextHolder.getContext().setAuthentication(
						authenticate);
			}
		} catch (AuthenticationException e) {
			throw new NegocioException(
					ConstantesMensagens.MSG_ERRO_LOGIN_INCORRETO, e);
		}
	}

	/**
	 * Recupera o usuário logado no sistema.
	 * 
	 * @return Usuário logado no sistema.
	 */
	public Usuario getUsuarioLogado() {
		return (Usuario) SecurityContextHolder.getContext().getAuthentication()
				.getPrincipal();
	}

	/**
	 * Verifica se o usuário logado possui o perfil inormado.
	 * 
	 * @param perfil
	 *            Perfil para verificaçãoo.
	 * @return true caso o usuário possuir o perfil informado, false caso
	 *         contrário.
	 */
	public boolean possuiPerfil(String perfil) {
		boolean retorno = false;

		for (GrantedAuthority authority : SecurityContextHolder.getContext()
				.getAuthentication().getAuthorities()) {

			String perfilUsuario = authority.getAuthority();
			if (perfil.equals(perfilUsuario)) {
				retorno = true;
				break;
			}
		}

		return retorno;
	}

	/**
	 * Verifica se o usu�rio logado possui algum perfil.
	 * 
	 * @return true caso o usu�rio logado possua algum perfil, false caso
	 *         contr�rio.
	 */
	public boolean possuiPerfil() {
		return !SecurityContextHolder.getContext().getAuthentication()
				.getAuthorities().isEmpty();
	}

	/**
	 * Realiza o logoout no sistema.
	 */
	public void logout() {
		SecurityContextHolder.getContext().setAuthentication(null);
		invalidarSessao();
	}

	private void invalidarSessao() {
		FacesContext fc = FacesContext.getCurrentInstance();
		HttpSession session = (HttpSession) fc.getExternalContext().getSession(
				false);
		session.invalidate();
	}

	@Override
	public UserDetails loadUserByUsername(String email)
			throws UsernameNotFoundException {
		// Funciona funciona = funcionaMediator.buscarPorEmail(email);
		// if (funciona == null) {
		// throw new UsernameNotFoundException("Funcionário com email "
		// + email + " não encontrado.");
		// }

		return null;
	}

	public AuthenticationManager getAuthenticationManager() {
		return authenticationManager;
	}

	public void setAuthenticationManager(
			AuthenticationManager authenticationManager) {
		this.authenticationManager = authenticationManager;
	}

	// public FuncionaMediator getFuncionaMediator() {
	// return funcionaMediator;
	// }
	//
	// public void setFuncionaMediator(FuncionaMediator funcionaMediator) {
	// this.funcionaMediator = funcionaMediator;
	// }

}